/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../macro/head.h"
#include "aio_epoll_notify.h"
#include "aio_helper.h"
#include "aio_tcp.h"
#include "aio_udp.h"
#include "head.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 
namespace xos_aio
{
    aio_helper::aio_helper( aio_impl * pAioImpl ) : m_pAioImpl( pAioImpl )
    {
    }

    aio_helper::~aio_helper()
    {
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int aio_helper::epoll_proc( aio_key * lpKey, int nFlags )
    {
        using namespace std;
        int nRet = 0;

        if( lpKey->m_nLastInstance != lpKey->m_nInstance )
        {
            cout << "stale event : m_nLastInstance" << endl;
            return 1;
        }

        switch( lpKey->m_enumHandleType )
        {
        case aio_key::H_TYPE_TCP_SERVER:
        case aio_key::H_TYPE_TCP_CONN:
        case aio_key::H_TYPE_TCP_NORM:
            {
                tcp_proc( lpKey, nFlags );
            }
            break;
        case aio_key::H_TYPE_UDP:
            {
                udp_proc( lpKey, nFlags );
            }
            break;
        default:
            {
                cout << "tcp_proc : unknown socket type" << endl;
            }
            break;
        }

        return nRet;
    }

    int aio_helper::tcp_proc( aio_key * lpKey, int nFlags )
    {
        using namespace std;
        int nRet = 0;

        aio_tcp tool( m_pAioImpl );

        switch( lpKey->m_enumHandleType )
        {
        case aio_key::H_TYPE_TCP_CONN:
            {
                tool.tcp_connect( lpKey );
            }
            break;
        case aio_key::H_TYPE_TCP_SERVER:
            {
                while( 0 == tool.tcp_accept( lpKey ) );
            }
            break;
        case aio_key::H_TYPE_TCP_NORM:
            {
                if( nFlags & EPOLLOUT )
                {
                    lpKey->m_bCanWrite = true;
                    while( 0 == tool.tcp_send( lpKey ) );
                }
                if( nFlags & EPOLLIN )
                {
                    while( 0 == tool.tcp_recv( lpKey ) );
                }
            }
            break;
        default:
            {
                cout << "tcp_proc : unknown socket type" << endl;
            }
            break;
        }

        return nRet;
    }

    int aio_helper::udp_proc( aio_key * lpKey, int nFlags )
    {
        using namespace std;
        int nRet = 0;

        aio_udp tool( m_pAioImpl );

        if( nFlags & EPOLLOUT )
        {
            lpKey->m_bCanWrite = true;
            while( 0 == tool.udp_send( lpKey ) );
        }
        if( nFlags & EPOLLIN )
        {
            while( 0 == tool.udp_recv( lpKey ) );
        }

        return nRet;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // will eat lpMsg
    // 
    int aio_helper::user_proc( xos_box::i_msg * lpMsg )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = user_tcp( lpMsg );
        }

        if( 0 == ret )
        {
            ret = user_udp( lpMsg );
        }

        return ret;
    }

    // 
    // will eat lpMsg
    // 
    int aio_helper::user_tcp( xos_box::i_msg * lpMsg )
    {
        int ret = 1;

        int eType = lpMsg->get_msg( 0, 0 );
        aio_tcp tcp( m_pAioImpl );

        switch( eType )
        {
        case i_aio::AIO_TCP_INIT:
            {
                tcp.user_init( lpMsg );
            }
            break;
        case i_aio::AIO_TCP_CONNECT:
            {
                tcp.user_connect( lpMsg );
            }
            break;
        case i_aio::AIO_TCP_ACCPET:
            {
            }
            break;
        case i_aio::AIO_TCP_RECV:
            {
            }
            break;
        case i_aio::AIO_TCP_SEND:
            {
                tcp.user_send( lpMsg );
            }
            break;
        case i_aio::AIO_TCP_SHUTDOWN:
            {
                tcp.shut_down( lpMsg );
            }
            break;
        case i_aio::AIO_TCP_CLOSE:
            {
                tcp.close_net( lpMsg );
            }
            break;
        default:
            {
                ret = 0;
            }
            break;
        }

        return ret;
    }

    // 
    // will eat lpMsg
    // 
    int aio_helper::user_udp( xos_box::i_msg * lpMsg )
    {
        int ret = 1;

        int eType = lpMsg->get_msg( 0, 0 );
        aio_udp udp( m_pAioImpl );

        switch( eType )
        {
        case i_aio::AIO_UDP_INIT:
            {
                udp.user_init( lpMsg );
            }
            break;
        case i_aio::AIO_UDP_RECV:
            {
            }
            break;
        case i_aio::AIO_UDP_SEND:
            {
                udp.user_send( lpMsg );
            }
            break;
        case i_aio::AIO_UDP_SHUTDOWN:
            {
                udp.shut_down( lpMsg );
            }
            break;
        case i_aio::AIO_UDP_CLOSE:
            {
                udp.close_net( lpMsg );
            }
            break;
        default:
            {
                ret = 0;
            }
            break;
        }

        return ret;
    }
    
} // xos_aio
